<?php


namespace app\api\logic;


use app\admin\user\logic\UserBalanceLogLogic;
use app\api\service\OrderFactory;
use app\model\order\Order;
use app\model\order\OrderDetail;
use app\model\pms\Goods;
use app\model\pms\GoodsSku;
use app\model\user\User;
use app\model\user\UserBalanceLog;
use Exception;
use plugin\coupon\app\admin\logic\CouponReceiveLogLogic;
use plugin\coupon\app\model\CouponReceiveLog;
use support\constants\QueueKey;
use support\Container;
use support\exception\BadException;
use support\Log;
use support\service\MqClient;
use support\utils\Form;
use support\utils\Time;
use think\db\exception\DbException;
use think\facade\Db;
use Webman\Config;
use Webman\Event\Event;
use Yansongda\Pay\Pay;

class OrderLogic extends \app\admin\order\logic\OrderLogic
{
    /**
     * @var CouponLogic
     */
    private CouponLogic $couponLogic;
    /**
     * @var CouponReceiveLogLogic
     */
    private CouponReceiveLogLogic $couponReceiveLogLogic;

    public function __construct()
    {
        parent::__construct();
        $this->couponLogic = new CouponLogic();
        $this->couponReceiveLogLogic = new CouponReceiveLogLogic();
    }

    public function orderCount($uid)
    {
        return [
            'wait_pay' => $this->model->where(['user_id' => $uid, 'status' => Order::STATUS_WAIT_PAID])->count(),
            'wait_tak' => $this->model->where(['user_id' => $uid, 'status' => Order::STATUS_WAIT_TAKE_DELIVERY])->count(),
            'refund' => $this->model->where(['user_id' => $uid, 'refund_status' => Order::REFUND_STATUS_REVIEW_ING])->count(),
        ];
    }

    public function preCreateOrder($input)
    {
        $strategy = OrderFactory::getOrderStrategy(Order::TYPE_NORMAL);
        return $strategy->preCreateOrder([
            "cart_ids" => $input['cart_ids'] ?? "", //购物车过来的
            "goods_id" => $input['goods_id'] ?? "", //直接购买
            "sku_id" => $input['sku_id'] ?? "", //直接购买
            "address_id" => $input['address_id'] ?? "", //前端变地址
            "coupon_id" => $input['coupon_id'] ?? 0, //选中的卡券 计算金额
            "uid" => request()->uid,
        ]);

    }

    public function createOrder($input)
    {
        $strategy = OrderFactory::getOrderStrategy(Order::TYPE_NORMAL);
        return $strategy->createOrder([
            "cart_ids" => $input['cart_ids'] ?? "",
            "goodsList" => $input['goodsList'] ?? [],
            "coupon_receive_log_id" => $input['coupon_receive_log_id'] ?? "", //使用了优惠券
            "address_id" => $input['address_id'] ?? "",
            "remark" => $input['remark'] ?? "",
            "uid" => request()->uid,
        ]);
    }

    /**
     * 关闭订单的后续操作
     * @param $order_no
     * @param array $updateOrder
     * @throws DbException
     */
    public function closeOrderOperation($order_no, array $updateOrder)
    {
        //回滚库存
        //回滚卡券  等待
        $order = Order::where(['order_no' => $order_no])->field([
            'order_no',
            'pay_status',
            'coupon_receive_log_id',
            'status',
        ])->find();
        $orderGoods = OrderDetail::where(['order_no' => $order_no])->select();
        $this->incrSkuStock($orderGoods);

        if ($order['coupon_receive_log_id'] > 0) {
            CouponReceiveLog::where([
                'id' => $order['coupon_receive_log_id'],
                'status' => CouponReceiveLog::STATUS_USED
            ])->update([
                'status' => CouponReceiveLog::STATUS_NO_USED,
                'order_id' => 0,
                'used_time' => null,
            ]);
        }

        Order::where(['order_no' => $order_no])
            ->update($updateOrder);
    }

    /**
     * 添加库存
     * @param $insertGoodsSku
     * @throws DbException
     */
    private function incrSkuStock($insertGoodsSku)
    {
        foreach ($insertGoodsSku as $value) {
            GoodsSku::where([
                ['sku_id', '=', $value['sku_id']],
            ])->update([
                'stock' => Db::raw("stock + ({$value['num']})")
            ]);
            Goods::where([
                ['id', '=', $value['goods_id']],
            ])->update([
                'stock' => Db::raw("stock + ({$value['num']})")
            ]);
        }
    }

    public function orderSimpleDetail($order_no)
    {
        $data = $this->model->where(['order_no' => $order_no])->find();

        if ($data) {
            $data['member_balance'] = User::where(['id' => request()->uid])->value('balance');
        }
        return $data;
    }

    /**
     * 确认支付
     * @param $order_no
     * @param $pay_way 1:微信 2:支付宝 3:余额
     */
    public function confirmPayment($order_no, $pay_way)
    {
        $order = Order::where(['order_no' => $order_no])->find();
        if (
            $order['pay_status'] !== Order::PAY_STATUS_WAIT &&
            $order['status'] !== Order::STATUS_WAIT_PAID
        ) {
            throw new BadException("订单已经支付");
        }
        if ($pay_way == Order::PAY_WAY_WECHAT_PAY) {
            throw new BadException("目前不支持微信支付");
        }
        $res = [];
        if ($pay_way == Order::PAY_WAY_ALI_PAY) {

            //目前先h5支付
            // 1. 获取配置文件 config/payment.php
            $config = Config::get('payment');

            // 2. 初始化配置
            Pay::config($config);

            // 3. 网页支付
            $order = [
                'out_trade_no' => $order_no,
                'total_amount' => $order['pay_price'],
                'subject' => '订单:' . $order_no,
                '_method' => 'post'
            ];
            try {
                $res['code'] = 200;
                $res['data'] = Pay::alipay()->h5($order)->getBody()->getContents();
                Order::where(['order_no' => $order_no])->update([
                    'pay_way' => Order::PAY_WAY_ALI_PAY,
                ]);
                Container::get(MqClient::class)->send(QueueKey::PAYMENT_QUERY, [
                    'order_no' => $order_no,
                ], 60);
            } catch (Exception $exception) {
                Log::channel("pay")->error("支付宝h5拉起支付失败:" . $exception->getTraceAsString());
                throw new BadException("拉起支付失败");
            }
        }

        if ($pay_way == Order::PAY_WAY_BALANCE) {
            //余额支付
            $bLogic = new UserBalanceLogLogic();
            if ($bLogic->checkBalance(request()->uid, $order['pay_price'])) {
                throw new BadException("剩余余额不足");
            }

            $bLogic->changeBalance(request()->uid, UserBalanceLog::TYPE_ORDER, -$order['pay_price'], [
                'remark' => $order_no . " 订单支付",
                'order_id' => $order['id'],
                'order_no' => $order_no,
            ]);
            Order::where(['order_no' => $order_no])->update([
                'pay_way' => Order::PAY_WAY_BALANCE,
                'pay_status' => Order::PAY_STATUS_PAID,
                'pay_time' => Time::now(),
                'status' => Order::STATUS_WAIT_DELIVERY,
            ]);
            $res = [
                'code' => 0 //表示已经付款成功
            ];
        }
        return $res;

    }


    public function orderList(Form $form)
    {
        $where = [
            ['user_del', '=', 0],
            ['user_id', '=', request()->uid],
        ];
        $form['status'] && $where[] = ['status', 'in', explode(',', $form['status'])];
        $form['refund_status'] && $where[] = ['refund_status', '=', $form['refund_status']];
        $form['user_comments'] && $where[] = ['user_comments', '=', $form['user_comments']];
        $query = $this->search($where);
        $query->order("create_time desc");
        $query->with([
            'user' => function ($query) {
                $query->field([
                    "id",
                    "username",
                    "nickname",
                    "avatar",
                    "mobile",
                ]);
            },
            'detail'
        ]);
        $data = $this->getPageList($query);
        $data['records'] = array_map(function ($v) {
            $v = $this->formatBtn($v);
            return $v;
        }, $data['records']);
        return $data;

    }

    /**
     * 显示哪些按钮
     * @param $item
     */
    public function formatBtn($item)
    {
        $action = [
            'cancel' => $item['status'] <= Order::STATUS_WAIT_PAID,  //取消订单
            'go_pay' => $item['status'] <= Order::STATUS_WAIT_PAID, //立即支付
            'take_delivery' => in_array($item['status'], [
                    Order::STATUS_WAIT_TAKE_DELIVERY
                ]) && $item['refund_status'] == Order::REFUND_STATUS_NORMAL, //立即收货
            'go_comment' => in_array($item['status'], [
                    Order::STATUS_TRANSACTION_COMPLETION
                ]) && $item['refund_status'] == Order::REFUND_STATUS_NORMAL, //去评价
            'go_refund' => in_array($item['status'], [
                    Order::STATUS_WAIT_DELIVERY,
                    Order::STATUS_WAIT_TAKE_DELIVERY,
//                    Order::STATUS_TRANSACTION_COMPLETION,
                    Order::STATUS_TRANSACTION_COMPLETION,
                ]) && $item['refund_status'] == Order::REFUND_STATUS_NORMAL, //申请退款
        ];
        $item['action'] = $action;
        return $item;

    }

    public function orderDetail($order_no)
    {
        $where = [
            ['order_no', '=', $order_no],
        ];
        $query = $this->search($where);
        $query->with([
            'user' => function ($query) {
                $query->field([
                    "id",
                    "username",
                    "nickname",
                    "avatar",
                    "mobile",
                ]);
            },
            'detail',
            'address',
        ]);
        $data = $query->find();
        $data = $this->formatBtn($data);
        return $data;
    }

    /**
     * 关闭未支付订单
     * @param $order_id
     * @throws BadException
     * @throws DbException
     */
    public function cancelOrder($order_id)
    {
        $order = Order::where(['id' => $order_id])->field([
            'order_no',
            'pay_status',
            'status',
        ])->find();
        if (
            $order['pay_status'] !== Order::PAY_STATUS_WAIT &&
            $order['status'] !== Order::STATUS_WAIT_PAID
        ) {
            throw new BadException("订单状态已经变化,不支持关闭");
        }
        Order::where(['id' => $order_id])->update([
            'status' => Order::STATUS_CANCEL,
            'cancel_time' => Time::now()
        ]);

        $this->closeOrderOperation($order['order_no'], [
            'status' => Order::STATUS_CANCEL,
            'cancel_time' => Time::now()
        ]);
    }

    public function takeDelivery($order_id)
    {
        $order = Order::where(['id' => $order_id])->find();
        if (
            $order['status'] !== Order::STATUS_WAIT_TAKE_DELIVERY
        ) {
            throw new BadException("订单还未发货,不可操作");
        }

        Order::where([
            'id' => $order_id,
            'status' => Order::STATUS_WAIT_TAKE_DELIVERY,
        ])
            ->update([
                'received_time' => Time::now(),
                'status' => Order::STATUS_TRANSACTION_COMPLETION,
            ]);
    }

    public function deleteOrder($order_id)
    {
        $order = Order::where(['id' => $order_id])->find();
        if (
            $order['status'] < 6
        ) {
            throw new BadException("订单状态正在进行中,不可删除");
        }
        Order::where(['id' => $order_id])->update(['user_del' => 1]);
    }

    /**
     * 支付成功回调
     * @param $out_trade_no
     * @param $third_code
     * @param $payWay
     */
    public function payFinished($out_trade_no, $third_code, $payWay)
    {
        $order = Order::where(['order_no' => $out_trade_no])->find();
        if (!$order) {
            Log::channel("pay")->error("订单不存在:[$out_trade_no]");
            return;
        }
        if ($order['pay_status'] !== Order::PAY_STATUS_WAIT &&
            $order['status'] !== Order::STATUS_WAIT_PAID
        ) {
            Log::channel("pay")->error("订单状态异常:[$out_trade_no]");
            return;
        }

        Order::where([
            'order_no' => $out_trade_no,
            'pay_status' => Order::PAY_STATUS_WAIT,
            'status' => Order::STATUS_WAIT_PAID,
        ])->update([
            'pay_status' => Order::PAY_STATUS_PAID,
            'status' => Order::STATUS_WAIT_DELIVERY,
            'third_code' => $third_code,
            'pay_time' => Time::now(),
            'pay_way' => $payWay == "alipay" ? Order::PAY_WAY_ALI_PAY : Order::PAY_WAY_WECHAT_PAY,
        ]);

        //处理优惠券
        //库存
        //处理用户等级之类的逻辑

        Event::dispatch('order.pay.success', $out_trade_no);
    }

}